/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package create_view_modify;

import cse308.entities.Degreeprogram;
import cse308.entities.Peo;
import cse308.entities.Studentoutcome;
import cse308.GUIUtilityClass;
import cse308.GeneralEntity;
import cse308.UserSessionBean;
import cse308.entities.Users;

import cse308.helper_classes.DegreeProgramClass;
import cse308.helper_classes.GeneralTest;
import cse308.helper_classes.PEOClass;
import cse308.helper_classes.StudentOutcomeClass;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

@ManagedBean(name = "degreeProgramBean")
@SessionScoped
public class DegreeProgramBean implements Serializable {

    @ManagedProperty(value = "#{gUIUtilityClass}")
    private GUIUtilityClass utilities;
    @ManagedProperty(value = "#{userSessionBean}")
    UserSessionBean userSessionBean;
    private String title;
    private String identifier;
    private Integer seqNum;
    private String description;
    private String department;
    private String peo;
    private final static Logger LOG = Logger.getLogger(GUIUtilityClass.class.getName());
    private List<DegreeProgramClass> degreeProgramClasses = new ArrayList();
    private List<String> pEOs;
    private List<PEOClass> allPEOs;
    private List<String> studentOutcomes;
    private List<StudentOutcomeClass> allStudentOutcomes;

    public DegreeProgramBean() {
    }

    public UserSessionBean getUserSessionBean() {
        return userSessionBean;
    }

    public void setUserSessionBean(UserSessionBean userSessionBean) {
        this.userSessionBean = userSessionBean;
    }

    public GUIUtilityClass getUtilities() {
        return utilities;
    }

    public void setUtilities(GUIUtilityClass utilities) {
        this.utilities = utilities;
    }

    public List<DegreeProgramClass> getDegreeProgramClasses() {
        return degreeProgramClasses;
    }

    public void setDegreeProgramClasses(List<DegreeProgramClass> degreeProgramClasses) {
        this.degreeProgramClasses = degreeProgramClasses;
    }

    public String getIdentifier() {
        return identifier;
    }

    public void setIdentifier(String identifier) {
        this.identifier = identifier;
    }

    public Integer getSeqNum() {
        return seqNum;
    }

    public void setSeqNum(Integer seqNum) {
        this.seqNum = seqNum;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public String getPeo() {
        return peo;
    }

    public void setPeo(String peo) {
        this.peo = peo;
    }

    public List<String> getpEOs() {
        return pEOs;
    }

    public void setpEOs(List<String> pEOs) {
        this.pEOs = pEOs;
    }

    public List<PEOClass> getAllPEOs() {
        return allPEOs;
    }

    public void setAllPEOs(List<PEOClass> allPEOs) {
        this.allPEOs = allPEOs;
    }

    public List<String> getStudentOutcomes() {
        return studentOutcomes;
    }

    public void setStudentOutcomes(List<String> studentOutcomes) {
        this.studentOutcomes = studentOutcomes;
    }

    public List<StudentOutcomeClass> getAllStudentOutcomes() {
        return allStudentOutcomes;
    }

    public void setAllStudentOutcomes(List<StudentOutcomeClass> allStudentOutcomes) {
        this.allStudentOutcomes = allStudentOutcomes;
    }

    public String createDegreeProgram() {


        EntityManagerFactory emf = Persistence.createEntityManagerFactory("CSE_308_ABETPU");
        EntityManager em = emf.createEntityManager();

        em.getTransaction().begin();
        Degreeprogram degreeprogram = new Degreeprogram();

        degreeprogram.setIdentifier(this.identifier);
        degreeprogram.setSeqNum(this.seqNum);
        degreeprogram.setDescription(this.description);
        degreeprogram.setDepartment(this.department);
        if (utilities.checkPK(degreeprogram)) {
            FacesMessage message = new FacesMessage();
            message.setDetail(GUIUtilityClass.createWarning);
            FacesContext.getCurrentInstance().addMessage("form", message);
            return "";
        }

        em.persist(degreeprogram);
        em.getTransaction().commit();



        return "welcome";
    }

    public String createDegreePrograms() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("CSE_308_ABETPU");
        EntityManager em = emf.createEntityManager();
        List<Studentoutcome> soEntity = em.createNamedQuery("Studentoutcome.findAll").getResultList();
        List<Peo> peoEntity = em.createNamedQuery("Peo.findAll").getResultList();

        for (Studentoutcome so : soEntity) {
            this.allStudentOutcomes.add(new StudentOutcomeClass(so));
        }
        for (Peo peos : peoEntity) {
            this.allPEOs.add(new PEOClass(peos));
        }

        return "CreateDegreeProgramsPage";
    }

    public String viewDegreePrograms() {
        title = "Degree Programs";
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("CSE_308_ABETPU");
        EntityManager em = emf.createEntityManager();
        Query degreePrograms = em.createNamedQuery("Degreeprogram.findAll");
        List<Degreeprogram> results = (List<Degreeprogram>) degreePrograms.getResultList();
        for (Degreeprogram i : results) {
            for (Users j : i.getUsersCollection()) {
                if (j.getUsername().equalsIgnoreCase(userSessionBean.getUsername())) {
                    LOG.info("Has Degree Programs in db");
                    DegreeProgramClass currentDegreeProgram = new DegreeProgramClass(i);
                    degreeProgramClasses.add(currentDegreeProgram);
                }
            }
        }

        Query PEOS = em.createNamedQuery("Peo.findAll");
        List<Peo> results2 = (List<Peo>) PEOS.getResultList();
        for (DegreeProgramClass i : degreeProgramClasses) {
            Map<String, String> mapForPEO = new HashMap();
            List<GeneralEntity> listOfPeos = i.findCorrespondingEntity().getAssociatedClass(Peo.class.getSimpleName());
            for (GeneralEntity ge : listOfPeos) {
                mapForPEO.put(ge.getIdentifier2(), ge.getIdentifier2());
            }
            i.setPeo(mapForPEO);
        }
        List<Studentoutcome> results3 = (List<Studentoutcome>) em.createNamedQuery("Studentoutcome.findAll").getResultList();
        for (DegreeProgramClass i : degreeProgramClasses) {
            Map<String, String> mapForStudentOutcomes = new HashMap();
            List<GeneralEntity> listOfStudentOutcomes = i.findCorrespondingEntity().getAssociatedClass(Studentoutcome.class.getSimpleName());
            for (GeneralEntity ge : listOfStudentOutcomes) {
                mapForStudentOutcomes.put(ge.getIdentifier2(), ge.getIdentifier2());
            }
            i.setStudentOutcomes(mapForStudentOutcomes);
        }
        return "degreeProgramPage";
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setSOForModify(EntityManager em, List<Studentoutcome> results3, int cmonth, int year, DegreeProgramClass i) {
        List<Studentoutcome> ownSO = em.createNamedQuery("Studentoutcome.findByDegreeProgramString").setParameter("degreeProgramString", i.getIdentifier()).getResultList();
        //List<Studentoutcome> activeSO = em.createNamedQuery("Studentoutcome.findByDegreeprogramAlt").setParameter("degreeprogramAlt", i.getIdentifier()).getResultList();

        List<StudentOutcomeClass> currentSO = new ArrayList();
        List<StudentOutcomeClass> ownSOClass = new ArrayList();

        for (Studentoutcome so : ownSO) {
            StudentOutcomeClass soc = new StudentOutcomeClass(so);
            if (checkIfValid(cmonth, year, so)) {
                currentSO.add(soc);
                ownSOClass.add(soc);
            }
        }

        List<Studentoutcome> nullPEOs = em.createNamedQuery("Studentoutcome.findAll").getResultList();
        for (Studentoutcome op : nullPEOs) {
            if (op.getDegreeprogram() == null) {
                currentSO.add(new StudentOutcomeClass(op));
            }
        }

        for (StudentOutcomeClass so : ownSOClass) {
            i.getOwnSOList().add(so.getIdentifier());
        }
        for (StudentOutcomeClass so : currentSO) {
            i.getAllSOList().add(so.getIdentifier());
            i.getStudentOutcomeMap().put(so.getIdentifier(), so);
        }
    }

    public void setGeneralized() {
    }

    public void setPEOForModify(EntityManager em, List<Peo> results2, Integer cmonth, Integer year, DegreeProgramClass i) {
        List<Peo> ownPEOs = em.createNamedQuery("Peo.findByDegreeProgramString").setParameter("degreeProgramString", i.getIdentifier()).getResultList();
        List<PEOClass> ownPEO = new ArrayList();
        List<PEOClass> currentPEOss = new ArrayList();
        for (Peo op : ownPEOs) {
            PEOClass pc = new PEOClass(op);
            if (this.checkIfValid(cmonth, year, op)) {
                currentPEOss.add(pc);
                ownPEO.add(pc);
            }
            LOG.info("added");
        }
        List<Peo> nullPEOs = em.createNamedQuery("Peo.findAll").getResultList();
        for (Peo op : nullPEOs) {
            if (op.getDegreeProgramString() == null) {
                currentPEOss.add(new PEOClass(op));
            }
        }

        for (PEOClass p : ownPEO) {
            i.getOwnPEOList().add(p.getIdentifier());
        }
        for (PEOClass p : currentPEOss) {
            i.addToMap(p.getIdentifier(), p);
            i.getAllPeoList().add(p.getIdentifier());
        }
    }

    public String modifyDegreePrograms() {
        int year = Calendar.getInstance().get(Calendar.YEAR);
        int month = Calendar.getInstance().get(Calendar.MONTH);
        int cmonth;
        if (month < 6) {
            cmonth = 0;
        } else {
            cmonth = 1;
        }

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("CSE_308_ABETPU");
        EntityManager em = emf.createEntityManager();

        List<Degreeprogram> results = em.createNamedQuery("Degreeprogram.findAll").getResultList();
        degreeProgramClasses = (List<DegreeProgramClass>) new ArrayList();
        for (Degreeprogram i : results) {
            List<String> path = new ArrayList();
            path.add("Users");
            if (GUIUtilityClass.isUserRole(path, 0, i)) {
                LOG.info("populate with degree programs");
                DegreeProgramClass currentDegreeProgram = new DegreeProgramClass(i);
                degreeProgramClasses.add(currentDegreeProgram);
            }

        }

        //All peos

        List<Peo> results2 = em.createNamedQuery("Peo.findAll").getResultList();
        List<Studentoutcome> results3 = em.createNamedQuery("Studentoutcome.findAll").getResultList();
        for (DegreeProgramClass i : degreeProgramClasses) {
            this.setPEOForModify(em, results2, cmonth, year, i);
            this.setSOForModify(em, results3, cmonth, year, i);
        }
        return "ModifyDegree";
    }

    public boolean checkIfValid(int cmonth, int year, Object peoOrStudent) {
        if (peoOrStudent instanceof Peo) {
            Peo op = (Peo) peoOrStudent;
            if (op.getYea() == null) {
                return false;
            }
            if (op.getYea() > year) {
                return false;
            }
            if (op.getYea() == year && op.getSemster() > cmonth) {
                return false;
            }
            if (op.getEndsemester() == null || op.getEndyear() == null) {
                return true;
            } else {
                if (op.getEndyear() <= year) {
                    return false;
                }
            }
            return true;
        } else {
            Studentoutcome op = (Studentoutcome) peoOrStudent;
            if (op.getYea() == null) {
                return false;
            }
            if (op.getYea() > year) {
                return false;
            }
            if (op.getYea() == year && op.getSemester() > cmonth) {
                return false;
            }
            if (op.getEndsemester() == null || op.getEndyear() == null) {
                return true;
            } else {
                if (op.getEndyear() <= year) {
                    return false;
                }
            }
        }
        return true;
    }

    public String saveDegreePrograms() {
        List<GeneralTest> gt = new ArrayList();
        for (int i = 0; i < this.degreeProgramClasses.size(); i++) {
            gt.add(this.degreeProgramClasses.get(i));
        }
        if (utilities.checkOneToMany(gt, -1)) {
            FacesMessage message = new FacesMessage();
            message.setDetail("For PEO and Student Outcome you can only associate an item with one Course Offering");
            FacesContext.getCurrentInstance().addMessage("form", message);
            return "ModifyDegree";
        }
        if (utilities.checkDuplicates(gt)) {
            FacesMessage message = new FacesMessage();
            message.setDetail(GUIUtilityClass.duplicateWarning);
            FacesContext.getCurrentInstance().addMessage("form", message);
            return "ModifyDegree";
        }

        int year = Calendar.getInstance().get(Calendar.YEAR);
        int month = Calendar.getInstance().get(Calendar.MONTH);
        int cmonth;
        if (month < 6) {
            cmonth = 0;
        } else {
            cmonth = 1;
        }

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("CSE_308_ABETPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        for (int i = 0; i < degreeProgramClasses.size(); i++) {
            DegreeProgramClass d1 = degreeProgramClasses.get(i);


            Degreeprogram d2 = (Degreeprogram) d1.findCorrespondingEntity();
            d2.setIdentifier(d1.getIdentifier());

            d2.setSeqNum(d1.getSeqNum());
            d2.setDescription(d1.getDescription());
            d2.setDepartment(d1.getDepartment());
            em.merge(d2);

            //user input
            List<String> ownPEOS2 = d1.getOwnPEOList();
            Map<String, PEOClass> dpc = d1.getPeoMap();
            List<PEOClass> ownPEOS = new ArrayList();
            for (int j = 0; j < ownPEOS2.size(); j++) {
                PEOClass currentDPC = dpc.get(ownPEOS2.get(j));
                ownPEOS.add(currentDPC);
            }
            //whats in database
            List<Peo> databasePEO = new ArrayList(d2.getPeoCollection());
            for (int j = 0; j < databasePEO.size(); j++) {
                if (!checkIfValid(cmonth, year, databasePEO.get(j))) {
                    databasePEO.remove(j);
                }
            }

            //copies
            List<Peo> peos = new ArrayList();
            peos.addAll(databasePEO);

            List<PEOClass> ownPEOS3 = new ArrayList();
            ownPEOS3.addAll(ownPEOS);

            for (int j = 0; j < ownPEOS.size(); j++) {
                for (int k = 0; k < databasePEO.size(); k++) {
                    String identifier2 = ownPEOS.get(j).getIdentifier();
                    String usertodegreeprogram = databasePEO.get(k).getIdentifier();
                    if (identifier2.equals(usertodegreeprogram)) {
                        ownPEOS3.remove(ownPEOS.get(j));
                        peos.remove(databasePEO.get(k));
                    }
                }
            }

            for (int j = 0; j < ownPEOS3.size(); j++) {
                Peo peo2 = em.find(Peo.class, ownPEOS3.get(j).getIdentifier());
                peo2.setSemster(cmonth);
                peo2.setYea(year);
                peo2.setEndsemester(null);
                peo2.setEndyear(4000);
                d2.getPeoCollection().add(peo2);
                peo2.setDegreeProgramString(d2);
                em.merge(d2);
                em.merge(peo2);
            }
            for (int j = 0; j < peos.size(); j++) {
                Peo peo3 = peos.get(j);
                peo3.setEndsemester(cmonth);
                peo3.setEndyear(year);
                d2.getPeoCollection().remove(peo3);
                peo3.setDegreeProgramString(null);
                em.merge(d2);
                em.merge(peo3);
            }

            //user input
            List<String> ownStudentOutcome2 = d1.getOwnSOList();
            Map<String, StudentOutcomeClass> dps = d1.getStudentOutcomeMap();
            List<StudentOutcomeClass> ownStudentOutcome = new ArrayList();
            for (int j = 0; j < ownStudentOutcome2.size(); j++) {
                ownStudentOutcome.add(dps.get(ownStudentOutcome2.get(j)));
            }
            //whats in database
            List<Studentoutcome> databaseStudentOutcome = new ArrayList(d2.getStudentoutcomeCollection());
            // em.createNamedQuery("Studentoutcome.findByDegreeprogramAlt").setParameter("degreeprogramAlt", d1.getIdentifier()).getResultList();
            for (Studentoutcome so : databaseStudentOutcome) {
                Integer endYear = so.getEndyear();
                if (endYear != null && endYear < year) {
                    databaseStudentOutcome.remove(so);
                    continue;
                }
                Integer endSemester = so.getEndsemester();
                if (endSemester != null && endSemester < cmonth) {
                    databaseStudentOutcome.remove(so);
                }
            }
            //List<Degreeprogramtostudentoutcome> databaseSOMulti = em.createNamedQuery("Degreeprogramtostudentoutcome.findByDegreeprogram").setParameter("degreeprogram", d1.getIdentifier()).getResultList();

            //copies
            List<Studentoutcome> databaseStudentOutcome2 = new ArrayList();
            databaseStudentOutcome2.addAll(databaseStudentOutcome);

            List<StudentOutcomeClass> ownStudentOutcome3 = new ArrayList();
            ownStudentOutcome3.addAll(ownStudentOutcome);

            // List<Degreeprogramtostudentoutcome> databaseSOMulti2 = new ArrayList();
            //databaseSOMulti2.addAll(databaseSOMulti);

            for (int j = 0; j < ownStudentOutcome.size(); j++) {
                for (int k = 0; k < databaseStudentOutcome.size(); k++) {
                    String identifier2 = ownStudentOutcome.get(j).getIdentifier();
                    String usertodegreeprogram = databaseStudentOutcome.get(k).getIdentifier();
                    if (identifier2.equals(usertodegreeprogram)) {
                        ownStudentOutcome3.remove(ownStudentOutcome.get(j));
                        databaseStudentOutcome2.remove(databaseStudentOutcome.get(k));
                    }
                }
            }
            for (int j = 0; j < ownStudentOutcome3.size(); j++) {
                Studentoutcome studentOutcome2 = em.find(Studentoutcome.class, ownStudentOutcome3.get(j).getIdentifier());
                studentOutcome2.setSemester(cmonth);
                studentOutcome2.setYea(year);
                studentOutcome2.setEndsemester(null);
                studentOutcome2.setEndyear(null);
                d2.getStudentoutcomeCollection().add(studentOutcome2);
                studentOutcome2.setDegreeprogram(d2);
                em.merge(d2);
                em.merge(studentOutcome2);
            }
            for (int j = 0; j < databaseStudentOutcome2.size(); j++) {
                Studentoutcome so3 = databaseStudentOutcome2.get(j);
                so3.setEndsemester(cmonth);
                so3.setEndyear(year);
                d2.getStudentoutcomeCollection().remove(so3);
                so3.setDegreeprogram(null);
                em.merge(d2);
                em.merge(so3);
            }
        }
        em.getTransaction().commit();
        LOG.info("Commits entities to DB");

        return "ModifyDegree";
    }
}
